#include <QCoreApplication>
#include <QSettings>
#include <QTextCodec>
#include <QFile>
#include <QTextStream>
#include <QDir>
#include <QDateTime>
#include <QDebug>
#include "cpublicdata.h"
#include "cclientdata.h"
#include "cglobal.h"
#include "cpublicfunc.h"

CPublicData::CPublicData()
{
    m_pMutex = new QMutex();
    m_bAutoStart = false;
    m_bServerRuninng = false;
    m_sCurVer = "V1.0.2025.0423";
    m_mapClient.clear();
    m_vecTag.clear();
    m_listClient.clear();
    m_vecTag.clear();
}

CPublicData::~CPublicData()
{
    for (QMap<QString, CClientData*>::iterator itor = m_mapClient.begin(); itor != m_mapClient.end(); itor++)
    {
        CClientData* pClient = itor.value();
        delete pClient;
        pClient = nullptr;
    }
    m_mapClient.clear();
    m_vecTagHistory.clear();
    if (m_pMutex != nullptr)
    {
        delete m_pMutex;
        m_pMutex = nullptr;
    }
}

void CPublicData::reLoad()
{
    loadIni();
    loadTag();
}

void CPublicData::reLoadClientTag(CClientData *pClient)
{
    m_nClientTagReload = enTagReloading;

    pClient->m_pMutex->lock();
    //清空该客户端的点表
    for (int i = 0; i < pClient->m_vecTag.size(); i++)
    {
        CTagData* pTag = pClient->m_vecTag[i];
        if (pTag == nullptr) continue;
        QMutexLocker locker(m_pMutex);
        m_vecTag.removeAll(pTag);
        SAFE_DELETE(pTag);
    }
    pClient->m_vecTag.clear();
    pClient->m_mapTag.clear();
    //重载点表
    if (pClient == nullptr) return;
    loadTagClient(pClient);

    pClient->m_pMutex->unlock();

    m_nClientTagReload = enTagUpDate;
}

void CPublicData::loadIni()
{
    QString sIniPath = QCoreApplication::applicationDirPath() + "/config/config.ini";
    QSettings settings(sIniPath, QSettings::IniFormat);
    settings.setIniCodec(QTextCodec::codecForName("UTF-8"));
    QStringList slistAllKeys = settings.allKeys();
    // 读取数据
    m_bAutoStart = settings.value("Main/AutoStart").toBool();
    m_stServerCfg.m_sServerIp = settings.value("Main/IP").toString();
    m_stServerCfg.m_nPort = settings.value("Main/Port").toInt();
    m_stServerCfg.m_nClientMax = settings.value("Main/ClientMaxNum").toInt();
    m_stServerCfg.m_nClientNum = settings.value("Main/ClientNum").toInt();
    bool bOK = false;
    m_stServerCfg.m_nReplyByte0 = (quint8)settings.value("TcpServer/ReplyByte0", "00").toString().toUInt(&bOK, 16);
    m_stServerCfg.m_nReplyByte1 = (quint8)settings.value("TcpServer/ReplyByte1", "ff").toString().toUInt(&bOK, 16);
    m_stServerCfg.m_nTagTimeOut = settings.value("TcpServer/TagTimeOut", 900).toInt();
    m_stSyncBaseCfg.m_sIp = settings.value("SyncBase/IP").toString();
    m_stSyncBaseCfg.m_sUser = settings.value("SyncBase/User").toString();
    m_stSyncBaseCfg.m_sPassWd = settings.value("SyncBase/PassWd").toString();
    m_stSyncBaseCfg.m_sDbName = settings.value("SyncBase/DbName").toString();
    m_stSyncBaseCfg.m_nPort = settings.value("SyncBase/Port").toInt();
    for (QMap<QString, CClientData*>::iterator itor = m_mapClient.begin(); itor != m_mapClient.end(); itor++)
    {
        CClientData* pClient = itor.value();
        delete pClient;
        pClient = nullptr;
    }
    m_mapClient.clear();
    m_listClient.clear();
    for (int i = 0; i < m_stServerCfg.m_nClientNum; i++)
    {
        bool bFind = false;
        for (const QString &key : slistAllKeys)
        {
            if (key.startsWith(QString("Client%1/").arg(i)))
            {
                bFind = true;
                break;
            }
        }
        if (bFind)
        {
            if (settings.contains(QString("Client%1/IP").arg(i)))
            {
                QString sIp = settings.value(QString("Client%1/IP").arg(i)).toString();
                QString sName = settings.value(QString("Client%1/ClientName").arg(i)).toString();
                int nPort = settings.value(QString("Client%1/Port").arg(i)).toInt();
                bool bEnabled = settings.value(QString("Client%1/Enabled").arg(i)).toBool();
                CClientData* pClient = new CClientData();
                pClient->m_sGuid = sIp;
                pClient->m_sIp = sIp;
                pClient->m_nPort = nPort;
                pClient->m_sName = sName;
                pClient->m_bEnabled = bEnabled;
                m_listClient.append(pClient);
                m_mapClient.insert(pClient->m_sIp, pClient);
            }
        }
    }
}

void CPublicData::loadTag()
{
    for (QMap<QString, CClientData*>::iterator itor = m_mapClient.begin(); itor != m_mapClient.end(); itor++)
    {
        CClientData* pClient = itor.value();
        pClient->m_bTagsReadReady = false;
        loadTagClient(pClient);
        pClient->m_bTagsReadReady = true;
    }
}

void CPublicData::loadTagClient(CClientData *pClient)
{
    QString sFilePath = QCoreApplication::applicationDirPath() + "/TagCfg/" + pClient->m_sName + "/" + pClient->m_sName + ".csv";
    QFile file(sFilePath);
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        return;
    }
    QTextStream in(&file);

    // 读取所有行
    QStringList listLines;
    QString sReadAll;
    while (false == in.atEnd())
    {
        QString sLine = in.readLine();
        listLines.append(sLine);
        sReadAll += sLine + "\n";
    }
    if (listLines.size() < 2)
    {
        //"文件内容不足，至少需要时间行和标题行！";
        return;
    }
    pClient->m_nCRC = PubFunc::CPublicFunc::crc16ForString(sReadAll.toStdString());
    // 处理每一行数据
    for (int i = 0; i < listLines.size(); ++i)
    {
        QString sLine = listLines[i];
        if (true == sLine.startsWith("#")) continue;
        QStringList data = sLine.split(",");

        if (data.size() < 11)
        {
            return;
        }
        CTagData* pTagData = new CTagData();
        pTagData->m_nIndex = data[0].toUInt();
        pTagData->m_sTagName = data[1];
        pTagData->m_sTagDesc = data[2];
        pTagData->m_nScanRate = data[3].toInt();
        pTagData->m_sDataAccess = data[4];
        pTagData->m_nDataType = data[5].toInt();
        pTagData->m_sCollectDrv = data[6];
        pTagData->m_sCollectAddr = data[7];
        pTagData->m_sKeyAddr = data[8];
        pTagData->m_dDeadband = data[9].toDouble();
        pTagData->m_nExceptionReport = data[10].toInt();
        pClient->m_vecTag.push_back(pTagData);
        m_vecTag.push_back(pTagData);
        pClient->m_mapTag.insert(pTagData->m_nIndex, pTagData);
    }
    pClient->m_nPointCount = pClient->m_vecTag.count();
    file.close();
}

void CPublicData::saveIni()
{
    QString sIniPath = QCoreApplication::applicationDirPath() + "/config/config.ini";
    QSettings settings(sIniPath, QSettings::IniFormat);
    settings.setIniCodec(QTextCodec::codecForName("UTF-8"));
    //Main
    settings.setValue("Main/IP", m_stServerCfg.m_sServerIp);
    settings.setValue("Main/Port", QString::number(m_stServerCfg.m_nPort));
    settings.setValue("Main/ClientMaxNum", QString::number(m_stServerCfg.m_nClientMax));
    settings.setValue("Main/ClientNum", QString::number(m_stServerCfg.m_nClientNum));
    settings.setValue("Main/AutoStart", QString::number(m_bAutoStart ? 1 : 0));
    settings.setValue("TcpServer/ReplyByte0", QString("%1").arg(m_stServerCfg.m_nReplyByte0, 2, 16, QLatin1Char('0')));
    settings.setValue("TcpServer/ReplyByte1", QString("%1").arg(m_stServerCfg.m_nReplyByte1, 2, 16, QLatin1Char('0')));
    settings.setValue("TcpServer/TagTimeOut", m_stServerCfg.m_nTagTimeOut);
    //Syncbase
    settings.setValue("SyncBase/IP", m_stSyncBaseCfg.m_sIp);
    settings.setValue("SyncBase/User", m_stSyncBaseCfg.m_sUser);
    settings.setValue("SyncBase/PassWd", m_stSyncBaseCfg.m_sPassWd);
    settings.setValue("SyncBase/DbName", m_stSyncBaseCfg.m_sDbName);
    settings.setValue("SyncBase/Port", QString::number(m_stSyncBaseCfg.m_nPort));
    //Client
    for (int i = 0; i < m_listClient.size(); i++)
    {
        CClientData* pData = m_listClient.value(i);
        QString sClientName = "Client" + QString::number(i);
        settings.setValue(sClientName + "/ClientName", pData->m_sName);
        settings.setValue(sClientName + "/IP", pData->m_sIp);
        settings.setValue(sClientName + "/Port", QString::number(pData->m_nPort));
        settings.setValue(sClientName + "/Enabled", pData->m_bEnabled ? "1" : "0");
    }
}

void CPublicData::saveTag()
{
    for (int i = 0; i < m_listClient.size(); i++)
    {
        if (m_listClient.at(i) == nullptr) continue;
        QString sGuid = m_listClient.at(i)->m_sGuid;
        saveTag(sGuid);
    }
}

void CPublicData::saveTag(const QString &sGuid)
{
    if (true == sGuid.isEmpty()) return;
    CClientData* pClient = m_mapClient.value(sGuid);
    if (nullptr == pClient) return;
    QString sFilePath = QCoreApplication::applicationDirPath() + "/TagCfg/" + pClient->m_sName + "/";
    QFileInfo infoFile(sFilePath);
    //路径不存在则创建
    if (false == infoFile.exists())
    {
        QDir dirParent(sFilePath);
        dirParent.mkpath(".");
    }
    QString sDirPath = sFilePath + pClient->m_sName + ".csv";
    QFile file(sDirPath);
    if (false == file.open(QFile::WriteOnly | QFile::Truncate))
    {
        return;
    }
    QTextStream out(&file);

    //第一行
    out << "#gwtagfile,"<< m_sCurVer << ","
        << QDateTime::currentDateTime().toString("yyyy/MM/dd hh:mm:ss")
        << pClient->m_nCRC << "\n";

    //第二行
    out << "#index,name,desc,scanRate,dataAccess,dataType,dataCollectDrv,"
        << "dataCollectDrvAddr,keyAddr,deadband,exceptionReport" << "\n";

    QMutexLocker locker(pClient->m_pMutex);
    //测点数据
    for (int i = 0; i < pClient->m_vecTag.size(); i++)
    {
        CTagData* pData = pClient->m_vecTag.at(i);
        if (pData == nullptr) continue;
        out << pData->m_nIndex << ","
            << pData->m_sTagName << ","
            << pData->m_sTagDesc << ","
            << pData->m_nScanRate << ","
            << pData->m_sDataAccess << ","
            << pData->m_nDataType << ","
            << pData->m_sCollectDrv << ","
            << pData->m_sCollectAddr << ","
            << pData->m_sKeyAddr << ","
            << pData->m_dDeadband << ","
            << pData->m_nExceptionReport << "\n";
    }
    file.close();
}
